package com.kb.design.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.kb.design.constant.Constants;
import com.kb.design.dto.QueryChartDTO;
import com.kb.design.entity.CustomUser;
import com.kb.design.entity.DesignDept;
import com.kb.design.entity.DesignOrder;
import com.kb.design.entity.DesignProject;
import com.kb.design.enums.DesignStatus;
import com.kb.design.enums.ProjectStatus;
import com.kb.design.mapper.postgreSQL.*;
import com.kb.design.service.ChartService;
import com.kb.design.service.CustomUserService;
import com.kb.design.service.DeptService;
import com.kb.design.util.ColorUtils;
import com.kb.design.util.DateUtils;
import com.kb.design.vo.ProjectDataChartVO;
import com.kb.design.vo.chart.PersonProjectCount;
import com.kb.design.vo.chart.RisingSunMapVO;
import org.aspectj.weaver.ast.Var;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.chrono.ChronoLocalDate;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@Service
@DS("slave-1")
public class ChartServiceImpl implements ChartService {
    //颜色数组 #1a84e9 #5e54c2 #fa8f2d
//    private static final String[] COLORS = new String[]{"blue", "indigo", "yellow","#1f77b4","#393b79", "#5254a3",};
    @Resource
    private ProjectMapper projectMapper;
    @Resource
    private DesignOrderMapper designOrderMapper;
    @Resource
    private CustomUserMapper userMapper;
    @Resource
    private DeptService deptService;
    @Resource
    private DesignDeptMapper designDeptMapper;
    @Resource
    private ChartMapper chartMapper;
    @Resource
    private CustomUserService userService;


    @Override
    public List<RisingSunMapVO> risingSunMap(QueryChartDTO queryChartDTO) {
        List<RisingSunMapVO> list = new ArrayList<>();
        //查询部门
        List<DesignDept> designDepts;
        if (StringUtils.isNotBlank(queryChartDTO.getDepartmentId())) {
            String string = queryChartDTO.getDepartmentId();
            //查询页面所选部门
            List<Long> deptList = Arrays.stream(string.split(",")).map(Long::parseLong).collect(Collectors.toList());
            designDepts = designDeptMapper.selectBatchIds(deptList);
        } else {
            designDepts = deptService.querySecondaryDept();
        }
        for (DesignDept designDept : designDepts) {
            RisingSunMapVO risingSunMapVO = new RisingSunMapVO();
            risingSunMapVO.setName(designDept.getDeptName());
            //查询部门下的人
//            List<Long> ids = new ArrayList<>();
//            ids.add(designDept.getDeptId());
            List<DesignDept> deptList = deptService.queryAllDept(designDept.getDeptId());
            List<Long> longs = deptList.stream().map(DesignDept::getDeptId).collect(Collectors.toList());
            LambdaQueryWrapper<CustomUser> wrapper = Wrappers.lambdaQuery();
            wrapper.in(CustomUser::getDeptId, longs).eq(CustomUser::getDelFlag, Constants.DEL_FLAG_NO);
            List<CustomUser> userList = userMapper.selectList(wrapper);
            int projectNumber = 0;
            if (CollectionUtils.isNotEmpty(userList)) {
                List<RisingSunMapVO> userSunList = new ArrayList<>();
                for (CustomUser user : userList) {
                    RisingSunMapVO userSun = new RisingSunMapVO();
                    userSun.setName(user.getName());

                    userSunList.add(userSun);
                    //查询项目是当前人的项目
                    List<DesignProject> projectList = projectMapper.queryProjectListByPerson(Integer.valueOf(user.getCode()));
                    projectNumber += projectList.size();
                    if (CollectionUtils.isNotEmpty(projectList)) {
                        List<RisingSunMapVO> projectSunList = new ArrayList<>();
                        int personProjectNumber = 0;
                        for (DesignProject project : projectList) {
                            RisingSunMapVO projectSun = new RisingSunMapVO();
                            projectSun.setName(project.getProjectName());
                            projectSun.setValue(1);
                            projectSunList.add(projectSun);
                            personProjectNumber++;
                        }
                        //等于项目之和
                        userSun.setValue(personProjectNumber);
                        userSun.setChildren(projectSunList);
                    }
                }
                risingSunMapVO.setValue(projectNumber);
                risingSunMapVO.setChildren(userSunList);
            }
            list.add(risingSunMapVO);
        }
        return list;
    }


    @Override
    public Map<String, Object> ganttChart(QueryChartDTO queryChartDTO) {
        Map<String, Object> map = new HashMap<>();
        List<Map<String, Object>> projectList = new ArrayList<>();
        List<String> userList = new ArrayList<>();
        List<String> colorList = new ArrayList<>();

        //x轴 日期生成
        List<String> dateList = DateUtils.generateDateList(LocalDate.now());
        //查询设计区域 所有的设计中的项目
        List<DesignDept> designDepts;
        if (StringUtils.isNotBlank(queryChartDTO.getDepartmentId())) {
            String string = queryChartDTO.getDepartmentId();
            //查询页面所选部门
            List<Long> deptList = Arrays.stream(string.split(",")).map(Long::parseLong).collect(Collectors.toList());
            designDepts = designDeptMapper.selectBatchIds(deptList);

        } else {
            designDepts = deptService.querySecondaryDept();
        }
        //查询部门下的项目
        List<DesignProject> list = Collections.emptyList();
        for (DesignDept designDept : designDepts) {
            if (designDept.getDeptId() == 14) {
                list = chartMapper.getPageProjectBy2Dept(designDept.getDeptId(), DesignStatus.CHECK.getIndex());
            } else {
                list = chartMapper.getProjectBy2Dept(designDept.getDeptId(), DesignStatus.CHECK.getIndex());
            }
        }
        if (CollectionUtils.isNotEmpty(list)) {
            for (DesignProject designProject : list) {
                Map<String, Object> projectMap = new HashMap<>();
                projectMap.put("projectName", designProject.getProjectName());
//                    projectMap.put("projectId", designProject.getId());
                //查询当前项目的负责人
                String responsiblePersonId = designProject.getResponsiblePersonId();
                String nickName = userService.queryNickName(responsiblePersonId);
                projectMap.put("name", nickName);
                projectMap.put("completionRate", "");
                if (designProject.getCompletionRate() != null) {
                    projectMap.put("completionRate", designProject.getCompletionRate() + "%");
                }
                userList.add(nickName);
                //区间计算
                projectMap.put("start", DateUtils.getPositionInDateRange(LocalDate.from(designProject.getCreateTime())));
                projectMap.put("end", DateUtils.getPositionInDateRange(LocalDate.from(designProject.getProjectEndDate())));
                projectMap.put("createTime", DateUtil.format(designProject.getCreateTime(), "yyyy-MM-dd"));
                //todo
                projectMap.put("projectEndDate",designProject.getProjectEndDate());

                projectList.add(projectMap);
            }
        }

        //颜色
        List<String> collect = userList.stream().distinct().collect(Collectors.toList());
        for (int i = 0; i < collect.size(); i++) {
            colorList.add(ColorUtils.getColorByIndex(i));
        }
        // 去重
        projectList = projectList.stream()
                .filter(distinctByKey(map1 -> map1.get("projectName")))
                .collect(Collectors.toList());

//        map.put("userList", projectList);
//        map.put("projectList", collect);
        map.put("userList", collect);
        map.put("projectList", projectList);
        map.put("dateList", dateList);
        map.put("colorList", colorList);
        return map;
    }

    public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }

    @Override
    public ProjectDataChartVO getProjectDataChart(QueryChartDTO queryChartDTO) {
        List<Long> longs = Collections.emptyList();
        //部门查询条件
        if (StringUtils.isNotBlank(queryChartDTO.getDepartmentId())) {
            String string = queryChartDTO.getDepartmentId();
            //以,号分割成list
            List<Long> list = Arrays.stream(string.split(",")).map(Long::parseLong).collect(Collectors.toList());
            List<DesignDept> designDepts = this.getAllSubDeptByAncestors(list);
            longs = designDepts.stream().map(DesignDept::getDeptId).collect(Collectors.toList());
        } else {
            List<DesignDept> list = deptService.querySecondaryDept();
            List<DesignDept> designDepts = this.getAllSubDeptByAncestors(list.stream().map(DesignDept::getDeptId).collect(Collectors.toList()));
            longs = designDepts.stream().map(DesignDept::getDeptId).collect(Collectors.toList());
        }

        ProjectDataChartVO projectDataChartVO = new ProjectDataChartVO();
        List<ProjectDataChartVO.ProjectCount> projectCounts = new ArrayList<>();
        LambdaQueryWrapper<DesignProject> queryWrapper = Wrappers.lambdaQuery();
        if (CollectionUtils.isNotEmpty(longs)) {
            queryWrapper.in(DesignProject::getDesignDepartments, longs)
                    .or()
                    .in(DesignProject::getPageDepartments, longs);
        }

        List<DesignProject> projectList = projectMapper.selectList(queryWrapper);
        //查询未处理订单数据
        List<DesignOrder> designOrderList = designOrderMapper.selectList(Wrappers.lambdaQuery(DesignOrder.class).eq(DesignOrder::getStatus, 1));
        //        查询部门人数
        LambdaQueryWrapper<CustomUser> wrapper = Wrappers.lambdaQuery();
        if (CollectionUtils.isNotEmpty(longs)) {
            wrapper.in(CustomUser::getDeptId, longs);
        }
        List<CustomUser> userList = userMapper.selectList(wrapper);

        //分类项目 进行中2 待启动0指未下单1的订单数据 未下单
        if (CollectionUtils.isNotEmpty(designOrderList)) {
            ProjectDataChartVO.ProjectCount projectCount = new ProjectDataChartVO.ProjectCount();
            //统计里面的pinAmount
            BigDecimal pinAmount = designOrderList.stream().map(DesignOrder::getPinAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            projectCount.setProjectCount((long) designOrderList.size());
            projectCount.setPintCount(pinAmount);
            projectCount.setStatus(1);
            projectCounts.add(projectCount);
        }
        ProjectDataChartVO.ProjectCount inProject = new ProjectDataChartVO.ProjectCount();
        long count = projectList.stream().filter(project -> !project.getStatus().equals(DesignStatus.FINISH.getIndex())).count();
        //计算Pin的总和
        BigDecimal pinAmount = projectList.stream().filter(project -> !project.getStatus().equals(DesignStatus.FINISH.getIndex()))
                .map(DesignProject::getPinAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        inProject.setProjectCount(count);
        inProject.setPintCount(pinAmount);
        inProject.setStatus(2);
        //计算人均pin
        if (!userList.isEmpty()) {
            inProject.setPerCapitaPin(pinAmount.divide(new BigDecimal(userList.size()), 0, RoundingMode.HALF_UP));
        }

        ProjectDataChartVO.ProjectCount orderProject = new ProjectDataChartVO.ProjectCount();
        long orderCount = projectList.stream().filter(project -> Objects.isNull(project.getOrderId())).count();
        //计算Pin的总和
        BigDecimal OrderPinAmount = projectList.stream().filter(project -> Objects.isNull(project.getOrderId()))
                .map(DesignProject::getPinAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        orderProject.setProjectCount(orderCount);
        orderProject.setPintCount(OrderPinAmount);
        orderProject.setStatus(0);

        projectCounts.add(inProject);
        projectCounts.add(orderProject);

        projectDataChartVO.setIdleCount(userList.size());
        //查询的人数数组去除 项目参与人数组 即为闲置人数
        List<String> userCodeList = userList.stream().map(CustomUser::getCode).collect(Collectors.toList());
        List<Integer> relevantResponsiblePerson = new ArrayList<>();
        for (DesignProject designProject : projectList) {
            relevantResponsiblePerson.addAll(designProject.getRelevantResponsiblePerson());
        }
        //去重relevantResponsiblePerson
//        List<Integer> relevantResponsiblePersonList = relevantResponsiblePerson.stream().distinct().collect(Collectors.toList());
        //项目所经历人员集合
        Set<Integer> relevantResponsiblePersonSet = relevantResponsiblePerson.stream()
                .distinct()
                .collect(Collectors.toSet());

        Map<Long, CustomUser> userMap = userList.stream().collect(Collectors.toMap(CustomUser::getId, user -> user));
        // 找出不在项目参与人列表中的用户ID
        List<Long> idleUserIds = new ArrayList<>();
        for (String code : userCodeList) {
            Long userId = null;
            Long userCode = null;
            for (CustomUser user : userList) {
                if (user.getCode().equals(code)) {
                    userId = user.getId();
                    userCode = Long.valueOf(user.getCode());
                    break;
                }
            }
            if (userId != null && !relevantResponsiblePersonSet.contains(userCode.intValue())) {
                idleUserIds.add(userId);
            }
        }
        // 获取最终的闲置用户对象列表
        List<CustomUser> idleUsers = idleUserIds.stream()
                .map(userMap::get)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        // 设置闲置人数和具体人员名称（示例）
        projectDataChartVO.setIdleCount(idleUsers.size());
        String idlePersonNames = idleUsers.stream()
                .map(CustomUser::getName) // 假设 getName() 是获取用户名字的方法
                .collect(Collectors.joining("，"));
        projectDataChartVO.setIdlePerson(idlePersonNames);// 转换 userList 为 userId -> CustomUser 映射，便于后续查找


        //projectCounts根据status 倒序
        projectCounts.sort(Comparator.comparingInt(ProjectDataChartVO.ProjectCount::getStatus).reversed());
        projectDataChartVO.setProjectCounts(projectCounts);

        /**
         *  ====================================================饱和度===================================================================
         */
        List<ProjectDataChartVO.AchievementRate> achievementRate = this.getAchievementRate(queryChartDTO);
        projectDataChartVO.setAchievementRateList(achievementRate);
        return projectDataChartVO;
    }

    @Override
    public List<ProjectDataChartVO.AchievementRate> getAchievementRate(QueryChartDTO queryChartDTO) {
        //饱和度计算 先获取二级部门且 部门职能值设计的部门
        List<DesignDept> designDepts;
        if (StringUtils.isNotBlank(queryChartDTO.getDepartmentId())) {
            String string = queryChartDTO.getDepartmentId();
            //以,号分割成list
            List<Long> list = Arrays.stream(string.split(",")).map(Long::parseLong).collect(Collectors.toList());
            designDepts = designDeptMapper.selectBatchIds(list);
        } else {
            designDepts = deptService.querySecondaryDept();
//            designDepts = this.getAllSubDeptByAncestors(list.stream().map(DesignDept::getDeptId).collect(Collectors.toList()));
        }
        ArrayList<ProjectDataChartVO.AchievementRate> objects = new ArrayList<>();
        int color = 0;
        String[] allColors = ColorUtils.getAllColors();
        for (DesignDept dept : designDepts) {
            ProjectDataChartVO.AchievementRate achievementRate = new ProjectDataChartVO.AchievementRate();
            //饱和度计算：部门中进行中的项目pin数总和 / 部门人数目标PIN数总和
            //大部门下的项目 只统计检查之前的数据
            List<DesignProject> list = Collections.emptyList();
            if (dept.getDeptId() == 14) {
                list = chartMapper.getPageProjectBy2Dept(dept.getDeptId(), DesignStatus.CHECK.getIndex());
            } else {
                list = chartMapper.getProjectBy2Dept(dept.getDeptId(), DesignStatus.CHECK.getIndex());
            }
            BigDecimal pinAmountProjectCount = list.stream().map(DesignProject::getPinAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            //所有人的目标pin  todo 后续优化  可以缓存一个部门目标pin字段
            LambdaQueryWrapper<CustomUser> queryUserWrapper = Wrappers.lambdaQuery();
            //获取子部门
            List<DesignDept> allSubDepts = deptService.queryAllDept(dept.getDeptId());
            List<Long> ids = allSubDepts.stream().map(DesignDept::getDeptId).collect(Collectors.toList());
            queryUserWrapper.in(CustomUser::getDeptId, ids);
            List<CustomUser> userPinList = userMapper.selectList(queryUserWrapper);
            BigDecimal targetPinAmount = userPinList.stream()
                    .map(user -> Optional.ofNullable(user.getTargetPin()).orElse(BigDecimal.ZERO))
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            //判断除数不能为0
            if (targetPinAmount.compareTo(BigDecimal.ZERO) != 0) {
                BigDecimal saturation = pinAmountProjectCount.divide(targetPinAmount, 0, RoundingMode.HALF_UP);
                achievementRate.setAchievementRate(saturation);
            }
            achievementRate.setColor(allColors[color]);
            achievementRate.setDepartmentName(dept.getDeptName());
            achievementRate.setPersonNumber(userPinList.size());
            color++;
            objects.add(achievementRate);
        }

        return objects;
    }

    @Override
    public List<PersonProjectCount> personProjectCount(QueryChartDTO queryChartDTO) {
        List<PersonProjectCount> list = new ArrayList<>();
        //查询人员列表
        LambdaQueryWrapper<CustomUser> queryWrapper = Wrappers.lambdaQuery();
        List<Long> deptIdList;
        if (StringUtils.isNotBlank(queryChartDTO.getDepartmentId())) {
            String string = queryChartDTO.getDepartmentId();
            //以,号分割成list
            deptIdList = Arrays.stream(string.split(",")).map(Long::parseLong).collect(Collectors.toList());
        } else {
            List<DesignDept> designDepts = deptService.querySecondaryDept();
            deptIdList = designDepts.stream().map(DesignDept::getDeptId).collect(Collectors.toList());
        }
        List<DesignDept> allDepts = getAllSubDeptByAncestors(deptIdList);
        List<Long> longs = allDepts.stream().map(DesignDept::getDeptId).collect(Collectors.toList());
        queryWrapper.in(CustomUser::getDeptId, longs);
        queryWrapper.eq(CustomUser::getDelFlag, "0");
        List<CustomUser> userList = userMapper.selectList(queryWrapper);
        //正文 数据计算
        if (!CollectionUtils.isEmpty(userList)) {
            //优化思路  不要再循环里面查询数据库 直接一次性把本月的项目查询出来 统计的是本月项目且状态为进行中
            LocalDateTime now = LocalDateTime.now();
            LocalDateTime startOfMonth = now.withDayOfMonth(1).with(LocalTime.MIN);
            LambdaQueryWrapper<DesignProject> wrapper = Wrappers.lambdaQuery();
            wrapper
//                    .eq(DesignProject::getProjectStatusAuxiliary, ProjectStatus.IN_PROGRESS.getIndex())
                    .ge(DesignProject::getCreateTime, startOfMonth);

            List<DesignProject> projectList = projectMapper.selectList(wrapper);

            LocalDate localDate = LocalDate.now();
            for (CustomUser customUser : userList) {
                PersonProjectCount personProjectCount = new PersonProjectCount();
                personProjectCount.setPerson(customUser.getName());

                int onlineProject = 0;
                int noOrdered = 0;
                int stopProject = 0;
                int renewalProject = 0;
                int cancelProject = 0;
                BigDecimal pinCount = BigDecimal.ZERO;
                for (DesignProject designProject : projectList) {
                    //未下单项目
                    if (designProject.getOrderId() == null && Objects.equals(customUser.getCode(), designProject.getResponsiblePersonId())) {
                        noOrdered++;
                    }
                    //暂停项目
                    if (designProject.getProjectStatusAuxiliary().equals(ProjectStatus.STOP.getIndex()) && Objects.equals(customUser.getCode(), designProject.getResponsiblePersonId())
                            && designProject.isLifeCycle()) {
                        stopProject++;
                    }
                    //延期项目 投板日期 > 交付日期 或者 投板日期为空并且 交付日期 < 当日
                    if (Objects.equals(customUser.getCode(), designProject.getResponsiblePersonId()) && designProject.isLifeCycle() && !designProject.getProjectStatusAuxiliary().equals(ProjectStatus.STOP.getIndex())) {
                        //在线项目统计
                        onlineProject++;
                        //pin数合计
                        pinCount = pinCount.add(designProject.getPinAmount());
                        if (designProject.getLoadingPlateTime() != null && designProject.getLoadingPlateTime().isAfter(ChronoLocalDate.from(designProject.getProjectEndDate()))
                                || designProject.getLoadingPlateTime() == null && designProject.getProjectEndDate().isBefore(ChronoLocalDate.from(localDate.atStartOfDay()))) {
                            renewalProject++;
                        }
                    }
                    //终止项目
                    if (!designProject.isLifeCycle() && Objects.equals(customUser.getCode(), designProject.getResponsiblePersonId())) {
                        cancelProject++;
                    }
                }
                //区域为当前用户所在部门
                DesignDept designDept = designDeptMapper.selectById(customUser.getDeptId());
//                System.out.println(customUser.getDeptId() +"==========");
                personProjectCount.setArea(designDept.getDeptName());
                personProjectCount.setOnlineProject(onlineProject);
                personProjectCount.setNoOrdered(noOrdered);
                personProjectCount.setItemsOrdered(onlineProject + stopProject);
                personProjectCount.setStopProject(stopProject);
                personProjectCount.setRenewalProject(renewalProject);
                personProjectCount.setCancelProject(cancelProject);

                //饱和度 pinCount / 目标数
                BigDecimal targetPin = customUser.getTargetPin();
                if (targetPin != null && targetPin.compareTo(BigDecimal.ZERO) > 0) {
                    BigDecimal divide = pinCount.divide(targetPin, 2, RoundingMode.HALF_UP);
                    personProjectCount.setSaturation(divide.multiply(BigDecimal.valueOf(100)));
                }
                personProjectCount.setTargetProject(targetPin);
                list.add(personProjectCount);
            }
        }
        return list;
    }


    /**
     * 根据部门id查询所有子部门 使用ancestors父节点集合
     */
    public List<DesignDept> getAllSubDeptByAncestors(List<Long> list) {
        List<DesignDept> deptList = new ArrayList<>();
        for (Long l : list) {
            List<DesignDept> allSubDeptByAncestors = designDeptMapper.getAllSubDeptByAncestors(l);
            deptList.addAll(allSubDeptByAncestors);
        }
        return deptList;
    }

    /**
     * 根据部门id查询所有子部门
     */
    public List<DesignDept> getAllSubDepts(List<Long> list) {
        List<DesignDept> deptList = new ArrayList<>();
        for (Long dept : list) {
            List<DesignDept> designDepts = deptService.queryAllDept(dept);
            deptList.addAll(designDepts);
        }
        return deptList;
    }


    public static void main(String[] args) {


    }
}
